package com.kk.hystrix.demo.command;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy;
import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.HystrixThreadPoolProperties;

/**
* HystrixCommand4CircuitBreaker.java
* 类说明 TODO
*
* @author chengkai
* @date  2017年6月21日 上午10:52:47
*/
public class SemaphoreCircuitBreakerCommand extends HystrixCommand<String> {

    private static final Setter SETTER = Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("SemaphoreDemo"))
                .andCommandKey(HystrixCommandKey.Factory.asKey("Echo"))
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("SemaphoreThreadPool"))
                /*.andThreadPoolPropertiesDefaults(
                        HystrixThreadPoolProperties.Setter()
                        .withCoreSize(200)
                )*/
                .andCommandPropertiesDefaults(
                        HystrixCommandProperties.Setter()
                        //.withCircuitBreakerEnabled(true)
                        .withCircuitBreakerRequestVolumeThreshold(3)
                        //.withCircuitBreakerErrorThresholdPercentage(80)
                        // 设置为true,所有请求都将被拒绝,直接到fallback
                        //.withCircuitBreakerForceOpen(true)
                        // 设置为true,将忽略错误
                        .withCircuitBreakerForceClosed(true)
                        // 信号量隔离
                        //.withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)
                        // 最大并发数不能大于2
                        //.withExecutionIsolationSemaphoreMaxConcurrentRequests(2)
                        //.withMetricsRollingStatisticalWindowInMilliseconds(10000)
                        // 配置fallback方法的信号量,如果请求超过了并发信号量,则不会舱室调用getFallback方法,而是快速失败抛出HystrixRuntimeException异常
                        //.withFallbackIsolationSemaphoreMaxConcurrentRequests(2)
                        //.withExecutionTimeoutInMilliseconds(5000) // TODO
                );

    private String name;

    public SemaphoreCircuitBreakerCommand(String name) {
        /*Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("Semaphore Echo"))
        .andCommandKey(HystrixCommandKey.Factory.asKey("Echo"))
        .andCommandPropertiesDefaults(
                HystrixCommandProperties.Setter()
                .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)
                .withExecutionIsolationSemaphoreMaxConcurrentRequests(2)
        )*/
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
                // since we're doing work in the run() method that doesn't involve network traffic
                // and executes very fast with low risk we choose SEMAPHORE isolation
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        .withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)));
        this.name = name;
    }

    @Override
    protected String run() throws Exception {
        System.out.println("running run():" + name);
        int i = 0;
        while(true) {
            i++;
        }
        //return name;
    }

    @Override
    protected String getFallback() {
        System.out.println("CircuitBreaker fallback: " + name);
        return "fallback " + name;
    }

}
